#include "playhand.h"

// PlayHand的构造
PlayHand::PlayHand() {}

PlayHand::PlayHand(Cards &cards)
{
    // 1. 对扑克牌进行分类: 1张，2张，3张, 4张有多少种
    classify(cards);

    // 2. 对所出的扑克牌类型进行分类
    judgeCardType();
}

PlayHand::PlayHand(HandType type, Card::CardPoint pt, int extra)
{
    m_type = type;
    m_pt = pt;
    m_extra = extra;
}

// 获取所出牌的类型
PlayHand::HandType PlayHand::getHandType()
{
    return m_type;
}

// 获取所出牌的点数
Card::CardPoint PlayHand::getCardPoint()
{
    return m_pt;
}

// 获取所出牌的额外属性（所出牌的张数）
int PlayHand::getExtra()
{
    return m_extra;
}

// 比较自己与其它玩家所处的牌谁大
bool PlayHand::canBeat(const PlayHand &other)
{
    // 所出牌未知
    if (m_type == Hand_Unknown) {
        return false;
    }

    // 对方放弃出牌
    if (other.m_type == Hand_Pass) {
        return true;
    }
    // 我方所出牌为王炸
    if (m_type == Hand_Bomb_Jokers) {
        return true;
    }
    // 我方所出牌为炸弹
    if (m_type == Hand_Bomb && other.m_type >= Hand_Single && other.m_type <= Hand_Seq_Single) {
        return true;
    }
    // 双方所出牌的类型一致
    if (m_type == other.m_type) {
        if (m_type == Hand_Seq_Pair || m_type == Hand_Seq_Single) { // 双方所出牌为连对或顺子
            return m_pt > other.m_pt && m_extra == other.m_extra;
        } else {
            return m_pt > other.m_pt;
        }
    }
    return false;
}

// 对扑克牌进行分类
void PlayHand::classify(Cards &cards)
{
    CardList list = cards.toCardList();
    int cardRecord[Card::Card_End]; // 记录每张扑克牌的张数
    memset(cardRecord, 0, sizeof(int) * Card::Card_End);

    // 将扑克牌的点数(CardPoint)与cardRecord数组的下标相对应
    for (int i = 0; i < list.size(); ++ i) {
        Card c = list.at(i);
        cardRecord[c.getPoint()]++;
    }

    m_oneCard.clear();
    m_twoCard.clear();
    m_threeCard.clear();
    m_fourCard.clear();

    for (int i = 0; i < Card::Card_End; ++ i) {
        if (cardRecord[i] == 1) {
            m_oneCard.push_back(static_cast<Card::CardPoint>(i));
        } else if (cardRecord[i] == 2) {
            m_twoCard.push_back(static_cast<Card::CardPoint>(i));
        } else if (cardRecord[i] == 3) {
            m_threeCard.push_back(static_cast<Card::CardPoint>(i));
        } else if (cardRecord[i] == 4) {
            m_fourCard.push_back(static_cast<Card::CardPoint>(i));
        }
    }
}

// 对牌型进行分类
void PlayHand::judgeCardType()
{
    m_type = Hand_Unknown;
    m_pt = Card::Card_Begin;
    m_extra = 0;


    if(isPass())
    {
        m_type = Hand_Pass;
    }

    if(isSingle())
    {
        m_type = Hand_Single;
        m_pt = m_oneCard[0];
    }
    else if(isPair())
    {
        m_type = Hand_Pair;
        m_pt = m_twoCard[0];
    }
    else if(isTriple())
    {
        m_type = Hand_Triple;
        m_pt = m_threeCard[0];
    }
    else if(isTripleSingle())
    {
        m_type = Hand_Triple_Single;
        m_pt = m_threeCard[0];
    }
    else if(isTriplePair())
    {
        m_type = Hand_Triple_Pair;
        m_pt = m_threeCard[0];
    }
    else if(isPlane())
    {
        m_type = Hand_Plane;
        // 记录点数最小的牌
        m_pt = m_threeCard[0];
    }
    else if(isPlaneTwoSingle())
    {
        m_type = Hand_Plane_Two_Single;
        // 记录点数最小的牌
        m_pt = m_threeCard[0];
    }
    else if(isPlaneTwoPair())
    {
        m_type = Hand_Plane_Two_Pair;
        // 记录点数最小的牌
        m_pt = m_threeCard[0];
    }
    else if(isSeqPair())
    {
        m_type = Hand_Seq_Pair;
        // 记录点数最小的牌
        m_pt = m_twoCard[0];
        m_extra = m_twoCard.size();
    }
    else if(isSeqSingle())
    {
        m_type = Hand_Seq_Single;
        // 记录点数最小的牌
        m_pt = m_oneCard[0];
        m_extra = m_oneCard.size();
    }
    else if(isBomb())
    {
        m_type = Hand_Bomb;
        // 记录点数最小的牌
        m_pt = m_fourCard[0];
    }
    else if(isBombSingle())
    {
        m_type = Hand_Bomb_Single;
        // 记录点数最小的牌
        m_pt = m_fourCard[0];
    }
    else if(isBombPair())
    {
        m_type = Hand_Bomb_Pair;
        // 记录点数最小的牌
        m_pt = m_fourCard[0];
    }
    else if(isBombTwoSingle())
    {
        m_type = Hand_Bomb_Two_Single;
        // 记录点数最小的牌
        m_pt = m_fourCard[0];
    }
    else if(isBombJokers())
    {
        m_type = Hand_Bomb_Jokers;
    }
    /*
    else if(isBombJokersSingle())
    {
        m_type = Hand_Bomb_Jokers_Single;
    }
    else if(isBombJokersPair())
    {
        m_type = Hand_Bomb_Jokers_Pair;
    }
    else if(isBombJokersTwoSingle())
    {
        m_type = Hand_Bomb_Jokers_Two_Single;
    }
    */
}

// 放弃出牌
bool PlayHand::isPass()
{
    if(m_oneCard.size() == 0 && m_twoCard.isEmpty() && m_threeCard.isEmpty() && m_fourCard.isEmpty())
    {
        return true;
    }
    return false;
}

// 所出牌为单张扑克牌
bool PlayHand::isSingle()
{
    if (m_oneCard.size() == 1 && m_twoCard.isEmpty() && m_threeCard.isEmpty() && m_fourCard.isEmpty()) {
        return true;
    }
    return false;
}

// 所出牌为对子
bool PlayHand::isPair()
{
    if (m_oneCard.isEmpty() && m_twoCard.size() == 1 && m_threeCard.isEmpty() && m_fourCard.isEmpty()) {
        return true;
    }
    return false;
}

// 所处牌为3张相同的点数 例如: 3个3
bool PlayHand::isTriple()
{
    if (m_oneCard.isEmpty() && m_twoCard.isEmpty() && m_threeCard.size() == 1 && m_fourCard.isEmpty()) {
        return true;
    }
    return false;
}

// 所出牌为三带一
bool PlayHand::isTripleSingle()
{
    if (m_oneCard.size() == 1 && m_twoCard.isEmpty() && m_threeCard.size() == 1 && m_fourCard.isEmpty()) {
        return true;
    }
    return false;
}

// 所出牌为三带二
bool PlayHand::isTriplePair()
{
    if (m_oneCard.isEmpty() && m_twoCard.size() == 1 && m_threeCard.size() == 1 && m_fourCard.isEmpty()) {
        return true;
    }
    return false;
}

// 所出牌为飞机 例如: 333 444
bool PlayHand::isPlane()
{
    if (m_oneCard.isEmpty() && m_twoCard.isEmpty() && m_threeCard.size() == 2 && m_fourCard.isEmpty()) {
        std::sort(m_threeCard.begin(), m_threeCard.end());
        // 飞机的点数一定相邻，并且点数不能为2
        if (m_threeCard[1] - m_threeCard[0] == 1 && m_threeCard[1] < Card::Card_2) {
            return true;
        }
    }

    return false;
}

// 所出牌飞机带两单
bool PlayHand::isPlaneTwoSingle()
{
    if (m_oneCard.size() == 2 && m_twoCard.isEmpty() && m_threeCard.size() == 2 && m_fourCard.isEmpty()) {
        std::sort(m_threeCard.begin(), m_threeCard.end());
        std::sort(m_oneCard.begin(), m_oneCard.end());
        if (m_threeCard[1] - m_threeCard[0] == 1 &&
            m_threeCard[1] < Card::Card_2 &&
            m_oneCard[0] != Card::Card_SJ &&
            m_oneCard[1] != Card::Card_BJ) {
            return true;
        }
    }
    return false;
}

// 所出牌飞机带2对
bool PlayHand::isPlaneTwoPair()
{
    if(m_oneCard.isEmpty() && m_twoCard.size() == 2 && m_threeCard.size() == 2 && m_fourCard.isEmpty()) {
        std::sort(m_threeCard.begin(), m_threeCard.end());
        if(m_threeCard[1] - m_threeCard[0] == 1 && m_threeCard[1] < Card::Card_2) {
            return true;
        }
    }
    return false;
}

// 所出牌为连对
bool PlayHand::isSeqPair()
{
    if (m_oneCard.isEmpty() && m_twoCard.size() >= 3 && m_threeCard.isEmpty() && m_fourCard.isEmpty()) {
        std::sort(m_twoCard.begin(), m_twoCard.end());
        if (m_twoCard.last() - m_twoCard.first() == (m_twoCard.size() - 1) &&
            m_twoCard.first() >= Card::Card_3 && m_twoCard.last() < Card::Card_2) {
            return true;
        }
    }
    return false;
}

// 所出牌为顺子
bool PlayHand::isSeqSingle()
{
    if (m_oneCard.size() >= 5 && m_twoCard.isEmpty() && m_threeCard.isEmpty() && m_fourCard.isEmpty()) {
        std::sort(m_oneCard.begin(), m_oneCard.end());
        if (m_oneCard.last() - m_oneCard.first() == (m_oneCard.size() - 1) &&
            m_oneCard.first() >= Card::Card_3 && m_oneCard.last() < Card::Card_2) {
            return true;
        }
    }
    return false;
}

// 所出牌为炸弹
bool PlayHand::isBomb()
{
    if (m_oneCard.isEmpty() && m_twoCard.isEmpty() && m_threeCard.isEmpty() && m_fourCard.size() == 1) {
        return true;
    }
    return false;
}

// 所出牌为炸弹带一单
bool PlayHand::isBombSingle()
{
    if (m_oneCard.size() == 1 && m_twoCard.isEmpty() && m_threeCard.isEmpty() && m_fourCard.size() == 1) {
        return true;
    }
    return false;
}

// 所出牌为炸弹带一对
bool PlayHand::isBombPair()
{
    if (m_oneCard.isEmpty() && m_twoCard.size() == 1 && m_threeCard.isEmpty() && m_fourCard.size() == 1) {
        return true;
    }
    return false;
}

// 所出牌为炸弹带两单
bool PlayHand::isBombTwoSingle()
{
    if (m_oneCard.size() == 2 && m_twoCard.isEmpty() && m_threeCard.isEmpty() && m_fourCard.size() == 1) {
        std::sort(m_oneCard.begin(), m_oneCard.end());
        if (m_oneCard.first() != Card::Card_SJ && m_oneCard.last() != Card::Card_BJ) {
            return true;
        }
    }
    return false;
}

// 所出牌为王炸
bool PlayHand::isBombJokers()
{
    if (m_oneCard.size() == 2 && m_twoCard.isEmpty() && m_threeCard.isEmpty() && m_fourCard.isEmpty()) {
        std::sort(m_oneCard.begin(), m_oneCard.end());
        if (m_oneCard.first() == Card::Card_SJ && m_oneCard.last() == Card::Card_BJ) {
            return true;
        }
    }
    return false;
}

/*
// 所出牌为王炸带一单
bool PlayHand::isBombJokersSingle()
{
    if (m_oneCard.size() == 3 && m_twoCard.isEmpty() && m_threeCard.isEmpty() && m_fourCard.isEmpty()) {
        std::sort(m_oneCard.begin(), m_oneCard.end());
        if (m_oneCard[1] == Card::Card_SJ && m_oneCard[2] == Card::Card_BJ) {
            return true;
        }
    }
    return false;
}

// 所出牌为王炸带一对
bool PlayHand::isBombJokersPair()
{
    if (m_oneCard.size() == 2 && m_twoCard.size() == 1 && m_threeCard.isEmpty() && m_fourCard.isEmpty()) {
        std::sort(m_oneCard.begin(), m_oneCard.end());
        if (m_oneCard[0] == Card::Card_SJ && m_oneCard[1] == Card::Card_BJ) {
            return true;
        }
    }
    return false;
}

// 所出牌为王炸带两单
bool PlayHand::isBombJokersTwoSingle()
{
    if (m_oneCard.size() == 4 && m_twoCard.isEmpty() && m_threeCard.isEmpty() && m_fourCard.isEmpty()) {
        std::sort(m_oneCard.begin(), m_oneCard.end());
        if (m_oneCard[2] == Card::Card_SJ && m_oneCard[3] == Card::Card_BJ) {
            return true;
        }
    }
    return false;
}
*/

